home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue26 / system / DLLPeek.pas next >
Encoding:
Pascal/Delphi Source File  |  1997-09-10  |  8.2 KB  |  219 lines

  1. unit DLLPeek;
  2.  
  3. interface
  4.  
  5. uses WinTypes, WinProcs, SysUtils, Classes;
  6.  
  7. procedure GetDLLList (const FileName: String; List: TStringList);
  8.  
  9. implementation
  10.  
  11. const
  12.     { Magic numbers }
  13.     DOS_Magic         = $5A4D;    { Magic word for old-style DOS EXE's    }
  14.     W16_Magic         = $454E;    { Magic word for new-style 16-bit EXE's }
  15.     W32_Magic         = $4550;    { Magic word for new-style 32-bit EXE's }
  16.  
  17.     { Error messages - should really go in resources ... }
  18.     eFileNotFound    = 'File not found';
  19.     eFileNotExe      = 'File is not a Windows 16-bit (NE) or 32-bit (PE) executable';
  20.  
  21. type
  22.     Directory = record
  23.         VirtualAddress: LongInt;
  24.         Size: LongInt;
  25.     end;
  26.  
  27.     PSection = ^Section;
  28.     Section = record
  29.         Name: array [0..7] of Char;  { name of this section }
  30.         VirtualSize: LongInt;        { size of code or data before rounding }
  31.         VirtualAddress: LongInt;     { RVA to where loader should map section }
  32.         SizeOfRawData: LongInt;      { size of code or data after rounding }
  33.         PointerToRawData: LongInt;   { file-based offset to raw data }
  34.         PointerToRelocs: LongInt;    { file-based offset to relocation info }
  35.         PointerToLineNums: LongInt;  { file-based offset to line number table }
  36.         NumRelocs: Word;             { number of relocations in table }
  37.         NumLineNums: Word;           { number of line numbers in table }
  38.         Flags: LongInt;              { flags for this section }
  39.     end;
  40.  
  41.     ImageImportDescriptor = record
  42.         Hints: LongInt;              { offset of hint import information }
  43.         TimeDataStamp: LongInt;      { time/date stamp of imported file  }
  44.         ForwarderChain: LongInt;     { for DLL call forwarding           }
  45.         Name: LongInt;               { RVA to name of this imported DLL  }
  46.         FirstThunk: LongInt;         { RVA to image_thunk_data info      }
  47.     end;
  48.  
  49.     PEHeader = record
  50.         Sig: LongInt;                             { $00 }
  51.         Machine: Word;                            { $04 }
  52.         NumSections: Word;                        { $06 }
  53.         TimeDataStamp: LongInt;                   { $08 }
  54.         PointerToSymbolTable: LongInt;            { $0C }
  55.         NumberOfSymbols: LongInt;                 { $10 }
  56.         SizeOfOptionalHeader: Word;               { $14 }
  57.         Characteristics: Word;                    { $16 }
  58.         Magic: Word;                              { $18 }
  59.         MajorLinkerVersion: Byte;                 { $1A }
  60.         MinorLinkerVersion: Byte;                 { $1B }
  61.         SizeOfCode: LongInt;                      { $1C }
  62.         SizeOfInitializedData: LongInt;           { $20 }
  63.         SizeOfUninitializedData: LongInt;         { $24 }
  64.         AddressOfEntryPoint: LongInt;             { $28 }
  65.         BaseOfCode: LongInt;                      { $2C }
  66.         BaseOfData: LongInt;                      { $30 }
  67.         ImageBase: LongInt;                       { $34 }
  68.         SectionAlignment: LongInt;                { $38 }
  69.         FileAlignment: LongInt;                   { $3C }
  70.         MajorOperatingSystemVersion: Word;        { $40 }
  71.         MinorOperatingSystemVersion: Word;        { $42 }
  72.         MajorImageversion: Word;                  { $44 }
  73.         MinorImageversion: Word;                  { $46 }
  74.         MajorSubsystemVersion: Word;              { $48 }
  75.         MinorSubsystemVersion: Word;              { $4A }
  76.         Reserved1: LongInt;                       { $4C }
  77.         SizeOfImage: LongInt;                     { $50 }
  78.         SizeOfHeaders: LongInt;                   { $54 }
  79.         CheckSum: LongInt;                        { $58 }
  80.         Subsystem: Word;                          { $5C }
  81.         DLLCharacteristics: Word;                 { $5E }
  82.         SizeOfStackReserve: LongInt;              { $60 }
  83.         SizeOfStackCommit: LongInt;               { $64 }
  84.         SizeOfHeapReserve: LongInt;               { $68 }
  85.         SizeOfHeapCommit: LongInt;                { $6C }
  86.         LoaderFlags: LongInt;                     { $70 }
  87.         NumberOfRvaAndSizes: LongInt;             { $74 }
  88.         ImageDirs: array [0..15] of Directory;    { $78 }
  89.     end;
  90.  
  91. procedure GetDLLList (const FileName: String; List: TStringList);
  92. var
  93.     fs: TFileStream;
  94.     HeaderPos: LongInt;
  95.  
  96.     function ReadByte: Byte;
  97.     begin
  98.         fs.Read (Result, sizeof (Result));
  99.     end;
  100.  
  101.     function ReadWord: Word;
  102.     begin
  103.         fs.Read (Result, sizeof (Result));
  104.     end;
  105.  
  106.     function ReadLong: LongInt;
  107.     begin
  108.         fs.Read (Result, sizeof (Result));
  109.     end;
  110.  
  111.     function ReadString: String;
  112.     var
  113.         Idx: Word;
  114.     begin
  115.         Result [0] := Char (ReadByte);
  116.         for Idx := 1 to Ord (Result [0]) do Result [Idx] := Char (ReadByte);
  117.     end;
  118.  
  119.     function ReadSZString (NewPos: LongInt): String;
  120.     var
  121.         Ch: Char;
  122.         OldPos: LongInt;
  123.     begin
  124.         Result := '';
  125.         OldPos := fs.Position;
  126.         fs.Position := NewPos;
  127.         repeat
  128.             Ch := Char (ReadByte);
  129.             if Ch <> #0 then Result := Result + Ch;
  130.         until Ch = #0;
  131.         fs.Position := OldPos;
  132.     end;
  133.  
  134.     procedure GetDLLList16;
  135.     var
  136.         Idx, Count: Integer;
  137.         OffsetListPos, ImpTabOffset: LongInt;
  138.     begin
  139.         with fs do begin
  140.             { Point to modtabentries count }
  141.             Position := HeaderPos + $1E;
  142.             Count := ReadWord;
  143.             { If zero, then this file needs no DLL's ! }
  144.             if Count <> 0 then begin
  145.                 Position := HeaderPos + $28;
  146.                 OffsetListPos := HeaderPos + ReadWord;
  147.                 { Now get location of import table }
  148.                 ImpTabOffset := HeaderPos + ReadWord;
  149.                 { Finally, loop for each item }
  150.                 for Idx := 0 to Count - 1 do
  151.                 begin
  152.                     Position := OffsetListPos + (Idx * sizeof (Word));
  153.                     Position := ImpTabOffset + ReadWord;
  154.                     List.Add (ReadString);
  155.                 end;
  156.             end;
  157.         end;
  158.     end;
  159.  
  160.     procedure GetDLLList32;
  161.     var
  162.         Idx: Integer;
  163.         Hdr: PEHeader;
  164.         ImportAddr: LongInt;
  165.         CurSection, SectionList: PSection;
  166.         ImportDescriptor: ImageImportDescriptor;
  167.     begin
  168.         with fs do begin
  169.             Position := HeaderPos;
  170.             fs.Read (Hdr, sizeof (Hdr));
  171.             ImportAddr := Hdr.ImageDirs [1].VirtualAddress;
  172.             { Allocate memory for section table }
  173.             GetMem (SectionList, sizeof (Section) * Hdr.NumSections);
  174.             fs.Read (SectionList^, sizeof (Section) * Hdr.NumSections);
  175.             try
  176.                 CurSection := SectionList;
  177.                 { Find the import table section }
  178.                 for Idx := 0 to Hdr.NumSections - 1 do
  179.                 begin
  180.                     if CurSection^.VirtualAddress = ImportAddr then begin
  181.                         fs.Position := CurSection^.PointerToRawData;
  182.                         { Read and process the Image Import Descriptors }
  183.                         repeat
  184.                             fs.Read (ImportDescriptor, sizeof (ImportDescriptor));
  185.                             if ImportDescriptor.Name = 0 then break;
  186.                             List.Add (ReadSZString (CurSection^.PointerToRawData +
  187.                                       ImportDescriptor.Name - CurSection^.VirtualAddress));
  188.                         until False;
  189.                     end;
  190.  
  191.                     Inc (CurSection);
  192.                 end;
  193.             finally
  194.                 FreeMem (SectionList, sizeof (Section) * Hdr.NumSections);
  195.             end;
  196.         end;
  197.     end;
  198.  
  199. begin
  200.     if not FileExists (FileName) then raise Exception.Create (eFileNotFound);
  201.     fs := TFileStream.Create (FileName, fmOpenRead);
  202.     with fs do try
  203.         if ReadWord <> DOS_Magic then raise Exception.Create (eFileNotExe);
  204.         Position := $3C; Position := ReadLong; HeaderPos := Position;
  205.         case ReadWord of
  206.              W16_Magic: GetDLLList16;
  207.              W32_Magic: GetDLLList32;
  208.              else       raise Exception.Create (eFileNotExe);
  209.         end;
  210.     finally
  211.         fs.Free;
  212.     end;
  213. end;
  214.  
  215. end.
  216.  
  217.  
  218.  
  219.